package impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.Executors;

import fr.irit.smac.may.lib.components.messaging.Sender;
import fr.irit.smac.may.lib.components.messaging.SenderImpl;
import fr.irit.smac.may.lib.components.messaging.receiver.AgentRef;
import fr.irit.smac.may.lib.components.messaging.receiver.Receiver;
import fr.irit.smac.may.lib.components.messaging.receiver.ReceiverImpl;
import fr.irit.smac.may.lib.components.meta.Forward;
import fr.irit.smac.may.lib.components.meta.ForwardImpl;
import fr.irit.smac.may.lib.components.scheduling.ExecutorService;
import fr.irit.smac.may.lib.components.scheduling.ExecutorServiceWrapperImpl;
import fr.irit.smac.may.lib.components.scheduling.Scheduler;
import fr.irit.smac.may.lib.components.scheduling.SchedulerImpl;
import fr.irit.smac.may.lib.interfaces.Send;
import impl.agentt.UneCaseImpl;
import impl.comp.AffichageImpl;
import impl.comp.GrilleImpl;
import impl.transverse.DataImpl;
import impl.transverse.LifeManagerImpl;
import interfaces.IInit;
import interfaces.agentt.ICreateAgent;
import message.InitAgent;
import message.SudoEMessage;
import debug.DebugIFace;
import debug.DebugImpl;
import sudoemerg.Affichage;
import sudoemerg.Data;
import sudoemerg.DebugCompo;
import sudoemerg.Grille;
import sudoemerg.Infr;
import sudoemerg.LifeManager;

public class InfrImpl extends Infr {
	LifeManagerImpl lifemanager;
	ReceiverImpl<SudoEMessage> referenceReceiver;
	SenderImpl<SudoEMessage, AgentRef> referenceSender;
	SchedulerImpl scheduler;
	DataImpl datat;
	ForwardImpl<DebugIFace> debugForward ;
	
	protected volatile long i = 0;
	
	@Override
	protected ICreateAgent createAgent() {
		return new ICreateAgent() {
			
			public AgentRef CreateAgent() {
				Case agent = new Case(new UneCaseImpl(),
						referenceReceiver.new AgentSide("Case_" + i++),
						referenceSender.new AgentSide(),
						lifemanager.new AgentSide(), scheduler.new AgentSide(),
						datat.new AgentSide(),
						debugForward.new AgentSide());

				agent.start();
				return agent.referenceReceiver().me().pull();
			}
		};
	}

	@Override
	protected ExecutorService make_executor() {
		return new ExecutorServiceWrapperImpl(Executors.newFixedThreadPool(8));
	}

	@Override
	protected DebugCompo make_debugC() {
		return new DebugImpl(true);
	}

	@Override
	protected Grille make_grille() {
		return new GrilleImpl();
	}

	@Override
	protected Data make_data() {
		datat = new DataImpl();
		return datat;
	}

	@Override
	protected LifeManager make_lifeManager() {
		lifemanager = new LifeManagerImpl();
		return lifemanager;
	}

	@Override
	protected Receiver<SudoEMessage> make_referenceReceiver() {
		referenceReceiver = new ReceiverImpl<SudoEMessage>();
		return referenceReceiver;
	}

	@Override
	protected Sender<SudoEMessage, AgentRef> make_referenceSender() {
		referenceSender = new SenderImpl<SudoEMessage, AgentRef>();
		return referenceSender;
	}

	@Override
	protected Scheduler make_scheduler() {
		scheduler = new SchedulerImpl();
		return scheduler;
	}

	@Override
	protected Forward<DebugIFace> make_debugForward() {
		debugForward = new ForwardImpl<DebugIFace>();
		return debugForward;
	}

	@Override
	protected IInit init() {
		return new IInit() {
			public void byData(int i) {
				ArrayList<AgentRef> agentts = new ArrayList<AgentRef>();
				grille().save().initByTest(i);
				for(int t=0; t<81; t++) {
					AgentRef agRef = createAgent().CreateAgent();
					grille().save().saveLink(agRef, t);
					agentts.add(agRef);
				}
				Iterator<AgentRef> iteAg = agentts.iterator();
				while(iteAg.hasNext()) {
					referenceReceiver().deposit().send(new InitAgent(), iteAg.next());
				}
			}
		};
	}

	@Override
	protected Affichage make_affichage() {
		// TODO Auto-generated method stub
		return new AffichageImpl();
	}
	
}
